PostgreSQL 安全管理 数据脱敏 Anonyimizer 脱敏规则

1 背景知识

脱敏规则应该由应用程序开发人员编写。因为他们最了解数据模型和工作原理。
脱敏规则应该直接在数据库内部直接执行,这是为了在数据库内部就可以脱敏数据,从而无需使用外部工具,从而限制了数据泄露的风险。

脱敏规则只需要使用 SECURITY LABEL 语句进行声明即可。

CREATE TABLE player( id SERIAL, name TEXT, points INT);

INSERT INTO player VALUES
  ( 1, 'Kareem Abdul-Jabbar', 38387),
  ( 5, 'Michael Jordan', 32292 );

SECURITY LABEL FOR anon ON COLUMN player.name
  IS 'MASKED WITH FUNCTION anon.fake_last_name()';

SECURITY LABEL FOR anon ON COLUMN player.id
  IS 'MASKED WITH VALUE NULL';

2 字符串字面转义

脱敏规则是放在单引号之间的。因此在脱敏规则中使用字符串时,需要使用 C-Style escapes 转义符,如下所示:

SECURITY LABEL FOR anon ON COLUMN player.name
  IS E'MASKED WITH VALUE \'CONFIDENTIAL\'';

或者可以使用 $ 符号,这样更加容易阅读。

SECURITY LABEL FOR anon ON COLUMN player.name IS 'MASKED WITH VALUE $CONFIDENTIAL$';

3 脱敏规则查看

查询 anon.pg_masking_rules 视图。

SELECT * FROM anon.pg_masking_rules;
//屏幕输出:
 relnamespace | relname  |  attname  | format_type |               col_description               |    masking_function    
--------------+----------+-----------+-------------+---------------------------------------------+------------------------
 public       | customer | full_name | text        | MASKED WITH FUNCTION anon.fake_first_name() | anon.fake_first_name()
 public       | customer | employer  | text        | MASKED WITH FUNCTION anon.fake_company()    | anon.fake_company()
 public       | customer | zipcode   | text        | MASKED WITH FUNCTION anon.random_zip()      | anon.random_zip()
 public       | people   | name      | text        | MASKED WITH VALUE $CONFIDENTIAL$          | 
 public       | people   | age       | integer     | MASKED WITH FUNCTION anon.noise(age, 0.33)  | anon.noise(age, 0.33)
(5 rows)

4 脱敏规则调试 Debugging

当设置了错误的脱敏规则而发生错误事,可以将 client_min_messages 参数设置为 DEBUG 获取更详细的问题信息。

SET client_min_messages=DEBUG;
SELECT anon.anonymize_database();
//屏幕输出:
SET
LOG:  statement: SELECT anon.anonymize_database();
DEBUG:  rehashing catalog cache id 7 for pg_attribute; 257 tups, 128 buckets
DEBUG:  Anonymize table public.customer with full_name = anon.fake_first_name(),employer = anon.fake_company(),zipcode = anon.random_zip()
DEBUG:  Anonymize table public.people with name = $CONFIDENTIAL$,age = anon.noise(age, 0.33)
 anonymize_database 
--------------------
 t
(1 row)

5 脱敏规则清除

通过 SECURITY LABEL 语句可以很轻松的移除脱敏规则。

SECURITY LABEL FOR anon ON COLUMN player.name IS NULL;

一次性删除所有规则,可以使用下面那条语句:

SELECT anon.remove_masks_for_all_columns();

6 脱敏规则的一些限制

限制1: 脱敏规则最多不能超过 1024 个字符!如果需要,可以专门写一个的脱敏函数
限制2:脱敏规则不会被继承!假设表将会变为分区表,则需要对每个分区进行脱敏规则的声明。